/**
 * Copyright (C), 2011-2016 The Store
 * File Name: MessagePushServlet.java
 * Encoding: UTF-8
 * Date: Feb 23, 2012
 * History: 
 */
package com.waynewan.qcomet.servlet;

import java.io.IOException;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.catalina.CometEvent;
import org.apache.catalina.CometProcessor;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.waynewan.qcomet.event.EventDispatcher;
import com.waynewan.qcomet.listener.AbstractListener;
import com.waynewan.qcomet.listener.RegisterService;
import com.waynewan.qcomet.message.QCommand;

/**
 *
 * @author Wayne Wan(bestirwiny@gmail.com)
 * @version Revision: 1.00 Date: Feb 23, 2012
 */
public class MessagePushServlet extends HttpServlet implements CometProcessor {
	
	private static Log log = LogFactory.getLog(MessagePushServlet.class);
	
	private static final long serialVersionUID = -2543529483319238703L;
	
	public static final String KEY_THREAD_POOL = "threadPoolSize";
	public static final String KEY_COMMAND     = "command";
	
	private ExecutorService threadPool;
	
	public void init() throws ServletException {
		log.debug("initialize the MessagePushServlet");
        int threadPoolSize = NumberUtils.toInt(getInitParameter(KEY_THREAD_POOL), 10);
        threadPool = Executors.newFixedThreadPool(threadPoolSize);
        RegisterService.initListeners(threadPool);
        EventDispatcher.createInstance(threadPool);
        testMsgSend();
    }

    public void destroy() {
    	threadPool.shutdown();
    }
	
	/* (non-Javadoc)
	 * @see org.apache.catalina.CometProcessor#event(org.apache.catalina.CometEvent)
	 */
	@Override
	public void event(CometEvent event) throws IOException, ServletException {
		HttpServletRequest request = event.getHttpServletRequest();
        HttpServletResponse response = event.getHttpServletResponse();
        response.addHeader("Access-Control-Allow-Origin", "*");
        String clientId = null;
        String command = request.getParameter(KEY_COMMAND);
        log.debug("command:" + command);
    	QCommand cmd = QCommand.parserCmd(command);
    	log.debug("clientId : " + cmd.getClient());
    	if(cmd.getClient().equalsIgnoreCase("none")) 
    		throw new RuntimeException("miss client id!");
    	else{
    		clientId = cmd.getClient();
    	}
    	/*
    	 * if the event listener does not exist, throw exception to end the session
    	 */
    	if(!RegisterService.isEventListenerExist(cmd.getEventName())) {
    		log.error("event[" + cmd.getEventName() + "] listener have not been registered yet");
			throw new RuntimeException("event[" + cmd.getEventName() + "] listener have not been registered yet");
    	}
    	AbstractListener listener = RegisterService.getEventListener(cmd.getEventName());
        if (event.getEventType() == CometEvent.EventType.BEGIN) {
        	log.debug("Begin for session: " + clientId);
        	if(cmd.getAction().equalsIgnoreCase(QCommand.ACTION_SUBSCRIPTION)){
        		log.debug(clientId + " subscript for the event listener : " + cmd.getEventName());
        		listener.addConn(clientId, event, response);
        	}else if(cmd.getAction().equalsIgnoreCase(QCommand.ACTION_UNSUBSCRIPTIONE)){
        		log.debug(clientId + " unsubscript for the event listener : " + cmd.getEventName());
        		listener.removeConn(clientId);
        		event.close();
        	}
        	else{
        		throw new RuntimeException("action not supported!");
        	}
        } else if (event.getEventType() == CometEvent.EventType.ERROR) {
            log.debug("Error for session: " + clientId);
            event.close();
            listener.removeConn(clientId);
        } else if (event.getEventType() == CometEvent.EventType.END) {
            log.debug("End for session: " + clientId);
            event.close();
            listener.removeConn(clientId);
        } else if (event.getEventType() == CometEvent.EventType.READ) {
        	log.debug("read for session: " + clientId);
        }
	}
	
	
	private void testMsgSend(){
		Thread tt = new Thread(new Runnable() {
			
			@Override
			public void run() {
				while(true){
					try {
						Thread.sleep(10*1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					EventDispatcher.getInstance().fire(null, "genericEvent", "Current datetime is : " + new Date());
				}
			}
		});
		tt.start();
	}
}
